/**
 * Runs the game
 * 
 * @authors Zachary Bellido, Adrian Alberto
 * @version 1.0.0
 */
import javax.swing.*;
import java.awt.Color;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
public class Runner implements ActionListener,KeyListener
{
    //Level related variables
    private static boolean nextLevelReady = false;
    private int readMeCt = 1;
    private Timer myTimer = new Timer(100, this);
    
    //GUI
    private JFrame frame;
    private Screen myScreen;
    private JTextArea text;
    static JTextArea status;
    private JPanel panel;
    
    //Player variables
    static Player player;
    public static int money;
    public int numProjectiles;
    public int health;
    
    //Player control variables
    public static boolean controlW;
    public static boolean controlA;
    public static boolean controlS;
    public static boolean controlD;
    public static boolean control8;
    public static boolean control4;
    public static boolean control5;
    public static boolean control6;
    
    /**
     * Main method. Runs the game
     * @pre         none
     * @param       none
     * @post        Game is running.
     * @return      none
     */
    public static void main (String [] args)
    {
        player = new Player('&', 0, 2);
        Grid.generateMap();
        Runner myRunner = new Runner();
    }

    
    /**
     * Constructs runner
     * @pre         none
     * @param       none
     * @post        Runner is constructed
     * @return      none
     */
    public Runner()
    {
        frame = new JFrame();
        text = new JTextArea(1,1);
        status = new JTextArea();
        panel = new JPanel();

        frame.getContentPane().add(BorderLayout.CENTER, panel);
        frame.getContentPane().add(BorderLayout.SOUTH, status);
        frame.setSize(520,600);
        frame.setResizable(false);
        frame.setVisible(true);

        frame.add(panel);
        panel.add(text);
        
        text.addKeyListener(this);

        myScreen = new Screen(text,status);

        myTimer.start();
        
    }

    /**
     * Calls the step() method every time the timer kicks.
     * @pre         Timer should be running
     * @param       ActionEvent
     * @post        Step is called.
     * @return      none
     */
    public void actionPerformed(ActionEvent ev)   
    {
        step();
    }

    /**
     * Required by interface. Not used by game.
     * @pre         none
     * @param       KeyEvent
     * @post        none
     * @return      none
     */
    public void keyTyped(KeyEvent event)
    {
    }

    /**
     * Key-Release event. Turns off controls.
     * @pre         none
     * @param       KeyEvent
     * @post        Control released is disabled.
     * @return      none
     */
    public void keyReleased(KeyEvent event)
    {

        switch (event.getKeyCode())
        {
            case KeyEvent.VK_W: controlW = false;
            break;
            case KeyEvent.VK_A: controlA = false;
            break;
            case KeyEvent.VK_S: controlS = false;
            break;
            case KeyEvent.VK_D: controlD = false;
            break;
            case KeyEvent.VK_NUMPAD8: control8 = false;
            break;
            case KeyEvent.VK_NUMPAD4: control4 = false;
            break;
            case KeyEvent.VK_NUMPAD5: control5 = false;
            break;
            case KeyEvent.VK_NUMPAD6: control6 = false;
            break;
            default: break;
        }
    }

    /**
     * Key-Press event. Turns on controls.
     * @pre         none
     * @param       KeyEvent
     * @post        Control released is enabled.
     * @return      none
     */
    public void keyPressed(KeyEvent event)
    {        

        switch (event.getKeyCode())
        {
            case KeyEvent.VK_W: controlW = true;
            break;
            case KeyEvent.VK_A: controlA = true;
            break;
            case KeyEvent.VK_S: controlS = true;
            break;
            case KeyEvent.VK_D: controlD = true;
            break;
            case KeyEvent.VK_NUMPAD8: control8 = true;
            break;
            case KeyEvent.VK_NUMPAD4: control4 = true;
            break;
            case KeyEvent.VK_NUMPAD5: control5 = true;
            break;
            case KeyEvent.VK_NUMPAD6: control6 = true;
            break;
            default: break;
        }
    }

    /**
     * Will process all entities actions every arbitrary amount of time
     * @pre         Timer must be enabled.
     * @param       none
     * @post        All entities perform their procedure, screen is updated.
     * @return      none
     */
    private void step()
    {
        
        if (!nextLevelReady) //Check to make sure you aren't in the process of loading a map.
        {
            //Have all entities perform their step procedure
            ArrayList<GridEntity> ents = Grid.getEntities();
            for (GridEntity e: ents){
                e.step();
            }
            
            //Any entities that requested to be added mid-step are dumped into the entity list.
            Grid.emptyQueue();
            
            //Copy health for display.
            health = player.getHP();
            
            //Display statistics and the map.

            numProjectiles = player.getNumProjectiles();
            status.setText("HP: " + health + " | " + "MONEY: " + money + " | " + "Projectiles: " + numProjectiles);
            myScreen.display();
            
        }
        else //Load the map.
        {
            //Display reward image/lore
            String str = ("./images/readme" + readMeCt + ".jpg");
            readMeCt++;
            DialogBox.popUp(str);
            
            //Reset controls
            controlW = false;
            controlA = false;
            controlS = false;
            controlD = false;
            control8 = false;
            control4 = false;
            control5 = false;
            control6 = false;
            //Reset health
            player.setHP(100);
            //Bump up difficulty and generate a new map.
            Grid.numMonsters += 2;
            Grid.generateMap();
            nextLevelReady = false;
        }
        //Clears entities not located on the map.
        ArrayList<GridEntity> ents = Grid.getEntities();
        for (int i = 0; i <- ents.size(); i++){
            if( ents.get(i).getCoordX() < 0 || ents.get(i).getCoordY() < 0){
                //ents.get(i).remove();
                i--;
            }
        }
            
    }
    
    /**
     * Requests for a map change.
     * @pre         none
     * @param       none
     * @post        Map will reload on next step.
     * @return      none
     */
    public static void nextLevel()
    {
        nextLevelReady = true;
    }
}